#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "automata.h"
#include "util.h"
#include "longInt.h"
#define DEBUG

#ifdef DEBUG
    #define DEBUGM  printf
#else
    #define DEBUGM  //
#endif



t_matrix
buildMatrix(int fil, int col)
{
    int i,j;
    t_matrix out;
    
    out.fils=fil;
    out.dimFils=fil+30;
    out.cols=col;
    if((out.data = malloc(sizeof(int *)*out.dimFils))== NULL)
        error(1,"Could not allocate memory. Shame on you.");
    
    for(i=0;i<out.dimFils;i++)
        out.data[i]=malloc(sizeof(int)*col);

    //Fill matrix with -1 which means the trap/error state transition
    for(i=0;i<out.dimFils;i++)
        for(j=0;j<col;j++)
            out.data[i][j] = -1;
            
    return out;
}

int
getSymIndex(char * alphabet, char symbol)
{
    int i,len;

    len=strlen(alphabet);

    //If it's a lambda transition, then return last matix column index    
    if(symbol == '^')
        return len;
    
    for(i=0;i<len;i++)
        if(alphabet[i] == symbol)
            break;

    return i==len?-1:i;
}

void
addTransition(t_table * t, int from_state, int symbol_index, int to_state)
{
    int state, prevSt, aux;
    t_longInt l;

    prevSt = t->transitions.data[from_state][symbol_index];
    if(prevSt == -1)
    {
        t->transitions.data[from_state][symbol_index] = to_state;
        return ;
    }

    longIntCpy(l,t->states.vec[prevSt]);
    turnOn(l,to_state);

    
    t->transitions.data[from_state][symbol_index] = 
        getStateIndex(t, l);            
}

int
getStateIndex(t_table * t, t_longInt l)
{
    int i, j, found;
    t_longInt acum;
    void * aux;
    
    for(i=0,found=0;i<t->states.dim;i++)
        if(longIntCmp(t->states.vec[i],l))
        {
            found=1;
            break;
        }

    //Add a new state
    if(!found)
    {
        //Allocate more space if needed
        if(t->states.dim == t->states.maxDim)
        {
            if((aux=realloc(t->states.vec,
                sizeof(t_longInt)* (t->states.maxDim *= 2)))==NULL)
                error(1,"Could not allocate memory. Shame on you.");
            else
                t->states.vec = aux;
        }
        //Add new state into states vector
        longIntCpy(t->states.vec[t->states.dim++],l);        
    
        //Check if new state is an acceptance one, then add it
        reset(acum);
        for(j=0;j<t->originalFinalDim;j++)
            longIntMerge(acum,t->finalStates.vec[j]);
        
        longIntAnd(acum,l);
        if(!isZero(acum))
        {
            //Allocate more space if needed
            if(t->finalStates.dim == t->finalStates.maxDim)
            {
                if((aux=realloc(t->finalStates.vec,
                    sizeof(t_longInt)* (t->finalStates.maxDim *= 2)))==NULL)
                    error(1,"Could not allocate memory. Shame on you.");
                else
                    t->finalStates.vec=aux;
            }
            //Add new state into final states vector
            longIntCpy(t->finalStates.vec[t->finalStates.dim++],l);
        }          
    } 

    return i;
}



int 
isFinalStInd(t_table *t, int state)
{
    int found, i;
    t_longInt word;
    
    longIntCpy(word, t->states.vec[state]);
    
    found = 0; // Needed in case vector is empty
    for (i = 0; i < t->finalStates.dim; i++)
        if (found = (longIntCmp(t->finalStates.vec[i], word)))
            break;
    
    return found;
}


